package com.davcam.testproject;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Vector;

import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.Toast;

/*-------------------------------------*\
||         C-D-Test-Project r14        ||
||            (aka) Cavdam             ||
||                                     ||
||      Created by David DeGroate      ||
||          and Cameron Tidd           ||
||           on Apr 11, 2012           ||
||                                     ||
||     Last updated on May 3, 2012     ||
\*-------------------------------------*/

/*-------------------------------------*\
||          Table of Contents          ||
||                                     ||
|| Global Initialization ...... [INIT] ||
|| Menu Settings .............. [MENU] ||
|| On-Screen Text Management .. [TXTM] ||
|| Player Commands ............ [PCOM] ||
|| Player Initialization ...... [PINI] ||
|| Player Navigation .......... [PNAV] ||
|| Preferences ................ [PREF] ||
|| PostgreSQL Database ........ [PSQL] ||
\*-------------------------------------*/

// JerkLib IRC Library -> http://jerklib.sourceforge.net/
// PostgreSQL from Android -> http://appliedcoffeetechnology.tumblr.com/post/10657124340
// Socket Example -> http://android-er.blogspot.com/2011/01/simple-communication-using.html

public class CdTestProjectActivity extends Activity {
	public Vector<String> textStorage;	// Stores the text to display on screen.
	private TextView tvDisplay;			// Where the text will be displayed on screen.
	private ScrollView svDisplay;		// Wraps the TextView and allows for scrolling.
	//private Button buttonNorth;			// Button for the Move North command.
	//private Button buttonSouth;			// Button for the Move South command.
	//private Button buttonEast;			// Button for the Move East command.
	//private Button buttonWest;			// Button for the Move West command.
	//private Button buttonLook;			// Button for the Look command.

	private String SERVER_IP = "192.168.1.104";				// Adjust the server IP Address!
	private int SERVER_PORT = 65123;						// Adjust the server Port!
	private final String DATABASE_NAME = "cavdam";			// Server database name.
	private final String DATABASE_USER = "raven";			// Server database login username.
	private final String DATABASE_PASS = "nevermore";		// Server database login password.

	private FetchSQL fetch;							//
	private boolean isConnectedToServer;			// Only true when the app is connected to the Cavdam server.
	private boolean connectionSuccessful;			// Indicates if the current connection attempt was successful.
	private final int MAX_CONNECTION_ATTEMPTS = 3;	// Limits the number of connection attempts.
	private int connectionAttempts;					// The current count of connection attempts.

	private boolean activityUserLeaving = false;	// Used to determine if user is intentionally destroying the activity.private Connection conn;	// The app's connection to the server.
	//private Connection saveStateActivityConnection;	// Save the app's server connection info during an app state change.
	//private Statement saveStateActivityStatement;	// Save the FetchSQL statement info during an app state change.
	//private String saveStateActivityURL;			// Save the server's URL during an app state change.
	//private int saveStatePlayerID = 0;				// Save the player's ID during an app state change.

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

		initializeSettings();
		addText("Welcome to the world of Cavdam, mortal!");

		// Open connections with the database when activity has started.
		if (fetch == null) {
			// Try to get a saved version of the connection.
			FetchSQL tempFetch = (FetchSQL) getLastNonConfigurationInstance();
			if (tempFetch != null) {
				fetch = tempFetch;
				addText(">> OLD FETCH PRESERVED <<"); // DEBUG
				initializePlayer();
			}
			else {
				// Open a new connection with the server.
				openServerConnection();
			}
		}
	}

	/** Called immediately after the activity is created. */
	@Override
	protected void onStart() {
		super.onStart();

		// Connect to the servers on activity start.
		if (fetch == null) {
			// Open connections with the database when activity has started.
			openServerConnection();
		}
	}

	/** Called when the activity resumes, prior to onStart(). */
	@Override
	public void onResume() {
		super.onResume();
		activityUserLeaving = false;

		// Apply changes once the preferences menu has been closed.
		updatePreferences();
	}

	/** Called when the activity has stopped. */
	@Override
	protected void onStop() {
		super.onStop();

		// Close connections because user is terminating the activity.
		if(activityUserLeaving) closeServerConnection();
	}

	/** Called immediately after onStop(). */
	@Override
	protected void onDestroy() {
		super.onDestroy();

		// Close connections because user is leaving the activity.
		if(isFinishing()) closeServerConnection();
	}

	@Override
	protected void onUserLeaveHint() {
		// Determines if onDestroy will be called to end the activity (true), or just rotate the screen (false).
		activityUserLeaving = true;
	}

	/** ONLY USE TO TRANSFER EXPENSIVE DATA -- OUT SERVER CONNECTION. */
	@Override
	public Object onRetainNonConfigurationInstance() {
		/*
		 * DO NOT USE TO TRANSFER DATA 
		 * USE onStaveInstanceState and onRestoreInstanceState INSTEAD!
		 */

		// Try to preserve the server connection.
		return fetch;
	}

	/** Used to restore primitive data and arrays from an activity state change. */
	@Override
	protected void onRestoreInstanceState(Bundle savedInstanceState) {
		super.onRestoreInstanceState(savedInstanceState);

		// Read values from the "savedInstanceState"-object
		if (savedInstanceState != null) {
			/*
			saveStatePlayerID = savedInstanceState.getInt("saveStatePlayerID");
			*/
		}
	}

	/** Used to preserve primitive data and arrays during an activity state change. */
	@Override
	protected void onSaveInstanceState(Bundle outState) {
		// Save the values you need into "outState"-object

		/*
		outState.putInt("saveStatePlayerID", playerInfo.getID());
		*/
		
		super.onSaveInstanceState(outState);       
	}

	/*==================================================================*\
    || [INIT]                Global Initialization                      ||
    \*==================================================================*/

	public void initializeSettings() {
		textStorage = new Vector<String>();

		// Text Display
		tvDisplay = (TextView)findViewById(R.id.text_display);
		svDisplay = (ScrollView)findViewById(R.id.scrollView_display);

		/* -----> Enable these to bypass XML Button method calls.

    	// Move North Button
    	buttonNorth = (Button)findViewById(R.id.button_cmdNorth);
    	buttonNorth.setOnClickListener(new View.OnClickListener() {
    		public void onClick(View v) {
    			moveNorth();
    		}
    	});

    	// Move South Button
    	buttonSouth = (Button)findViewById(R.id.button_cmdSouth);
    	buttonSouth.setOnClickListener(new View.OnClickListener() {
    		public void onClick(View v) {
    			moveSouth();
    		}
    	});

    	// Move East Button
    	buttonEast = (Button)findViewById(R.id.button_cmdEast);
    	buttonEast.setOnClickListener(new View.OnClickListener() {
    		public void onClick(View v) {
    			moveEast();
    		}
    	});

    	// Move West Button
    	buttonWest = (Button)findViewById(R.id.button_cmdWest);
    	buttonWest.setOnClickListener(new View.OnClickListener() {
    		public void onClick(View v) {
    			moveWest();
    		}
    	});

    	// Look Button
    	buttonLook = (Button)findViewById(R.id.button_cmdLook);
    	buttonLook.setOnClickListener(new View.OnClickListener() {
    		public void onClick(View v) {
    			cmdLook();
    		}
    	});

		 */
	}

	/*==================================================================*\
    || [MENU]                    Menu Settings                          ||
    \*==================================================================*/

	public boolean onCreateOptionsMenu(Menu menu) {
		MenuInflater inflater = getMenuInflater();
		inflater.inflate(R.menu.menu_main, menu);
		return true;
	}

	public boolean onOptionsItemSelected(MenuItem item) {
		switch(item.getItemId()) {
		case R.id.menu_reconnect:
			closeServerConnection();
			openServerConnection();
			return true;
		case R.id.menu_settings:
			openPreferences();
			return true;
		default:
		}
		return false;
	}

	/*==================================================================*\
    || [PREF]               Preferences & Settings                      ||
    \*==================================================================*/

	private Intent settingsActivity;
	public void openPreferences() {
		settingsActivity = new Intent(getBaseContext(), Preferences.class);
		startActivity(settingsActivity);
	}

	// Update changes from Preferences screen.
	private SharedPreferences preferences;
	//private Editor editor;
	private boolean keepScreenOn = true;   	// If true, keeps the screen on while the app is running.
	private String tempStr;
	//private int tempInt;
	public void updatePreferences() {
		preferences = PreferenceManager.getDefaultSharedPreferences(this);
		//editor = preferences.edit();

		// Server IP Address
		try {
			tempStr = preferences.getString("editPref_ServerIP", "192.168.1.100");
			//StringTokenizer tokenizer = new StringTokenizer(tempStr);
		} catch(Exception e) {
			tempStr = "192.168.1.100";
			Toast.makeText(getApplicationContext(), ("Error with server IP address. Reset to 192.168.1.100."), Toast.LENGTH_SHORT).show();
		}
		SERVER_IP = tempStr;

		// Screen Orientation ---> Code doesn't work as intended.
		/*
		if(preferences.getString("listLayout", "layoutPortrait").equalsIgnoreCase("layoutLandscape")) {
			setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
		}
		else {
			setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
		}
		 */

		// Screen Always On
		keepScreenOn = preferences.getBoolean("checkbox_ScreenOn", true);
		findViewById(R.id.mainView).setKeepScreenOn(keepScreenOn);
	}

	/*==================================================================*\
    || [PSQL]                 PostgreSQL Database                       ||
    \*==================================================================*/

	public void openServerConnection() {
		isConnectedToServer = false;
		connectionSuccessful = false;
		connectionAttempts = 0;
		addText(">> NEW FETCH EXECUTED <<"); // DEBUG
		addText("==============================\nConnecting to Cavdam server...");
		fetch = new FetchSQL();
		fetch.execute();
	}

	private class FetchSQL extends AsyncTask<Void,Void,String> {
		public Connection conn;		// The app's connection to the server.
		public Statement st;		//
		public String retval;		// Return value of query from server.
		public String url;			// The server's URL.
		public String sql;			// Server query.
		public ResultSet rs;		// Results gathered from server query.

		@Override
		protected String doInBackground(Void... params) {
			retval = "";

			// Load PostgreSQL driver from library.
			try {
				Class.forName("org.postgresql.Driver").newInstance();
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
				retval = e.toString();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
				retval = e.toString();
			} catch (InstantiationException e) {
				e.printStackTrace();
				retval = e.toString();
			} catch (Exception e) {
				e.printStackTrace();
				retval = e.toString();
			}

			// Initial server connection.
			url = "jdbc:postgresql://" + SERVER_IP + ":" + SERVER_PORT + "/" + DATABASE_NAME;
			conn = null;
			while(connectionAttempts < MAX_CONNECTION_ATTEMPTS) {
				try {
					connectionAttempts++;

					// Establish connection with PostgreSQL server database.
					DriverManager.setLoginTimeout(5);
					conn = DriverManager.getConnection(url, DATABASE_USER, DATABASE_PASS); 
					st = conn.createStatement();

					// Create simple query to test connection with database.
					sql = "SELECT 1";
					rs = st.executeQuery(sql);

					// Gather each result from the result set. (Just "1" in this case.)
					while(rs.next()) {
						retval = rs.getString(1);
					}

					// Check result, and edit confirmation for display.
					if(retval.equals("1")) retval = "...CHECK.";
					else retval = "...FAIL. :(";

					// Break out of while loop if/when query was successful within the alloted number of attempts.
					connectionSuccessful = true;
					break;
				} catch (SQLException e) {
					//e.printStackTrace();
					//retval = e.toString();
				} catch (RuntimeException e) {
					e.printStackTrace();
					retval = e.toString();
					break;
				} catch (Exception e) {
					e.printStackTrace();
					retval = e.toString();
					break;
				}
			}

			return retval;
		}

		// Output data gathered from query.
		@Override
		protected void onPostExecute(String value) {
			// Shows SQL query results or errors caught, if any.
			addText(value);

			// * Initial connection only.
			if(!isConnectedToServer) {
				// Display if initial server connection was successful or not.
				if(connectionSuccessful) {
					// Success on first attempt.
					if(connectionAttempts == 1)
						addText("Connection successful!\n==============================");
					// Success after several attempts. Alert user to number of attempts.
					else
						addText("Connection successful after " + connectionAttempts + " attempts!\n==============================");
					isConnectedToServer = true;

					// Initialize player.
					initializePlayer();
				}
				// Failed to connect after maximum attempts.
				else {
					addText("Connection failed after " + MAX_CONNECTION_ATTEMPTS + " attempts!");
				}
			}
		}
	}

	public ResultSet queryServer(String query, int params) {
		try {
			fetch.rs = fetch.st.executeQuery(query);
		} catch(SQLException e) {
			// Reestablish server connection?
			/*
			 * Let the originating function recall queryServer() if necessary.
			 */
		} catch(Exception e) {}

		return fetch.rs;
	}

	public void updateServer(String query) {
		try {
			fetch.rs = fetch.st.executeQuery(query);
		} catch(SQLException e) {
		} catch(Exception e) {}
	}

	public void closeServerConnection() {
		try { fetch.rs.close();
		} catch (SQLException e) {} catch (Exception e) {}
		try { fetch.st.close();
		} catch (SQLException e) {} catch (Exception e) {}
		try { fetch.conn.close();
		} catch (SQLException e) {} catch (Exception e) {}
		try { fetch.cancel(true);
		} catch (Exception e) {}
	}

	public boolean testConnection() {
		ResultSet testRS = queryServer("1", 1);
		try {
			if(testRS.getString(1).equals("1")) return true;
			else return false;
		}
		catch(SQLException e) {}
		catch(Exception e) {}

		return false;
	}

	/*==================================================================*\
    || [PINI]                Player Initialization                      ||
    \*==================================================================*/
	// Player initialization is currently called after successful connection in onPostExecute() within FetchSQL.

	private Player playerInfo;		// Stores player data locally for easier access.
	public void initializePlayer() {
		int playerID = 2; // DEBUG --> Loads Snarf.

		// Load player stats from server.
		ResultSet playerRS = queryServer("SELECT * FROM Character WHERE id = " + playerID, 14);
		/*
		 * 1:	ID				Integer [PK]	Player's ID number.
		 * 2:	Name			Text			Player's name.
		 * 3:	Level			Integer			Player's level.
		 * 4:	Experience		Integer			Player's experience points.
		 * 5:	HP				Integer			Player's current health.
		 * 6:	HP_Max			Integer			Player's maximum health.
		 * 7:	MP				Integer			Player's current mana.
		 * 8:	MP_Max			Integer			Player's maximum mana.
		 * 9:	STR				Integer			Player's strength.
		 * 10:	DEX				Integer			Player's dexterity.
		 * 11:	INT				Integer			Player's intellect.
		 * 12:	VIT				Integer			Player's vitality.
		 * 13:	LCK				Integer			Player's luck.
		 * 14:	Room_ID			Integer			Player's location.
		 */

		playerInfo = new Player(playerID);
		try {
			while(playerRS.next()) {
				if(playerRS.getString(2) != null) playerInfo.setName(playerRS.getString(2));
				if(playerRS.getString(3) != null) playerInfo.setLevel(Integer.parseInt(playerRS.getString(3)));
				if(playerRS.getString(4) != null) playerInfo.setEXP(Integer.parseInt(playerRS.getString(4)));
				if(playerRS.getString(5) != null) playerInfo.setHP(Integer.parseInt(playerRS.getString(5)));
				if(playerRS.getString(6) != null) playerInfo.setMaxHP(Integer.parseInt(playerRS.getString(6)));
				if(playerRS.getString(7) != null) playerInfo.setMP(Integer.parseInt(playerRS.getString(7)));
				if(playerRS.getString(8) != null) playerInfo.setMaxMP(Integer.parseInt(playerRS.getString(8)));
				if(playerRS.getString(9) != null) playerInfo.setSTR(Integer.parseInt(playerRS.getString(9)));
				if(playerRS.getString(10) != null) playerInfo.setDEX(Integer.parseInt(playerRS.getString(10)));
				if(playerRS.getString(11) != null) playerInfo.setINT(Integer.parseInt(playerRS.getString(11)));
				if(playerRS.getString(12) != null) playerInfo.setVIT(Integer.parseInt(playerRS.getString(12)));
				if(playerRS.getString(13) != null) playerInfo.setLCK(Integer.parseInt(playerRS.getString(13)));
				if(playerRS.getString(14) != null) playerInfo.setRoom(Integer.parseInt(playerRS.getString(14)));
			}
		} 
		catch(SQLException e) {
			// Test server connection, and reconnect if necessary.
			/*
			if(!testConnection()) {
				closeServerConnection();
				openServerConnection();
			}
			 */
		}
		catch(Exception e) {
			e.printStackTrace();
			addText(e.toString());
		}

		// Load room of player's current location.
		try {
			addText("Welcome back, " + playerInfo.getName() + "!");
			addText("LVL: " + playerInfo.getLevel() + "\t\tEXP: " + playerInfo.getEXP() + 
					"\nHP: " + playerInfo.getHP() + " \\ " + playerInfo.getMaxHP() + "\t\tMP: " + playerInfo.getMP() + " \\ " + playerInfo.getMaxMP() +
					"\nSTR: " + playerInfo.getSTR() + "\t\tDEX: " + playerInfo.getDEX() + "\t\tINT: " + playerInfo.getINT() +
					"\nVIT: " + playerInfo.getVIT() + "\t\tLCK: " + playerInfo.getLCK() +
					"\n=============================="); // DEBUG --> Show player info.
			loadRoom(playerInfo.getRoom());
		} catch(Exception e) { loadRoom(1); } // DEBUG VALUE
	}

	/*==================================================================*\
    || [PNAV]                  Player Navigation                        ||
    \*==================================================================*/

	private Room currentRoom;	// Stores data for the player's current room.
	public void loadRoom(int roomID) {
		// Load all info for the player's current room.
		ResultSet roomRS = queryServer("SELECT * FROM Room WHERE id = " + roomID, 8);
		/*
		 * 1: 	ID				Integer [PK]	Room's ID number.
		 * 2: 	Name			Text			Room's name.
		 * 3: 	Description		Text			Room's description.
		 * 4: 	North			Integer			Room's north connection.
		 * 5: 	South			Integer			Room's south connection.
		 * 6: 	East			Integer			Room's east connection.
		 * 7: 	West			Integer			Room's west connection.
		 * 8: 	Type			Integer			Room's type identifier.
		 */
		// NOTE: Player's initial room is loaded, after successful connection, in onPostExecute();

		currentRoom = new Room(roomID);
		try {
			while(roomRS.next()) {
				if(roomRS.getString(2) != null) currentRoom.setName(roomRS.getString(2));
				if(roomRS.getString(3) != null) currentRoom.setDescription(roomRS.getString(3));
				if(roomRS.getString(4) != null) currentRoom.setNorth(Integer.parseInt(roomRS.getString(4)));
				if(roomRS.getString(5) != null) currentRoom.setSouth(Integer.parseInt(roomRS.getString(5)));
				if(roomRS.getString(6) != null) currentRoom.setEast(Integer.parseInt(roomRS.getString(6)));
				if(roomRS.getString(7) != null) currentRoom.setWest(Integer.parseInt(roomRS.getString(7)));
				if(roomRS.getString(8) != null) currentRoom.setType(Integer.parseInt(roomRS.getString(8)));
			}
		} 
		catch(SQLException e) {
			// Test server connection, and reconnect if necessary.
			/*
			if(!testConnection()) {
				closeServerConnection();
				openServerConnection();
			}
			 */
		}
		catch(Exception e) {
			e.printStackTrace();
			addText(e.toString());
		}

		/* DEBUG TEXT TO VIEW ALL ROOM DATA.
		addText("ID:    " + currentRoom.getID() +
				"\nName:  " + currentRoom.getName() + 
				"\nDesc:  " + currentRoom.getDescription() + 
				"\nNorth: " + currentRoom.getNorth() + 
				"\nSouth: " + currentRoom.getSouth() + 
				"\nEast:  " + currentRoom.getEast() + 
				"\nWest:  " + currentRoom.getWest() + 
				"\nType:  " + currentRoom.getType());
		 */

		// Update player info to reflect location change.
		if(currentRoom.getID() != 0) {
			playerInfo.setRoom(currentRoom.getID());
			updateServer("UPDATE Character SET Room_ID = " + currentRoom.getID() + " WHERE id = " + playerInfo.getID());
		}

		// Display room data.
		String tempText = "";
		if(!currentRoom.getName().equals("")) {
			tempText = "~{ " + currentRoom.getName() + " }~";
		}

		if(!currentRoom.getDescription().equals("")) {
			tempText += "\n" + currentRoom.getDescription();
			addText(tempText);
		}
		else {
			addText(tempText);
			cmdLook(new View(this));
		}
	}

	public void moveNorth(View v) {
		// Player moves North, if able.

		if(currentRoom.getNorth() != 0) {
			addText("You travel north.\n==============================");
			loadRoom(currentRoom.getNorth());
		}
		else {
			// Check if connection to server must be restored.
			//if(!testConnection()) restoreConnection();

			addText("You cannot travel north from here.");
		}
	}

	public void moveSouth(View v) {
		// Player moves South, if able.

		if(currentRoom.getSouth() != 0) {
			addText("You travel south.\n==============================");
			loadRoom(currentRoom.getSouth());
		}
		else {
			// Check if connection to server must be restored.
			//if(!testConnection()) restoreConnection();

			addText("You cannot travel south from here.");
		}
	}

	public void moveEast(View v) {
		// Player moves East, if able.

		if(currentRoom.getEast() != 0) {
			addText("You travel east.\n==============================");
			loadRoom(currentRoom.getEast());
		}
		else {
			// Check if connection to server must be restored.
			//if(!testConnection()) restoreConnection();

			addText("You cannot travel east from here.");
		}

	}

	public void moveWest(View v) {
		// Player moves West, if able.

		if(currentRoom.getWest() != 0) {
			addText("You travel west.\n==============================");
			loadRoom(currentRoom.getWest());
		}
		else {
			// Check if connection to server must be restored.
			//if(!testConnection()) restoreConnection();

			addText("You cannot travel west from here.");
		}

	}

	/*==================================================================*\
    || [PCOM]                   Player Commands                         ||
    \*==================================================================*/

	public void cmdLook(View v) {
		// Player carefully looks around the room, paying attention to small details.

		//addText("Player looks around the screen, but finds little of interest. In the center, there is the block of text you\'re reading right now. To the south, the player sees five large buttons.");

		// Determine the number of paths from the current location.
		int numOfPaths = 0;
		if(currentRoom.getNorth() != 0) numOfPaths++;
		if(currentRoom.getSouth() != 0) numOfPaths++;
		if(currentRoom.getEast() != 0) numOfPaths++;
		if(currentRoom.getWest() != 0) numOfPaths++;

		String tempTxt;
		int z = 0;
		switch(numOfPaths) {
		case 4:
			addText("You may travel in any direction from this location.");
			break;
		case 3:	
			tempTxt = "You may travel ";
			for(int x = 0; x < 3; x++) {
				for(int y = z; y < 4; y++) {
					switch(y) {
					case 0:
						if(currentRoom.getNorth() != 0) {
							tempTxt += "north";
							z = 1;
							y = 4;
							break;
						}
					case 1:
						if(currentRoom.getSouth() != 0) {
							tempTxt += "south";
							z = 2;
							y = 4;
							break;
						}
					case 2:
						if(currentRoom.getEast() != 0) {
							tempTxt += "east";
							z = 3;
							y = 4;
							break;
						}
					case 3:
						if(currentRoom.getWest() != 0) {
							tempTxt += "west";
							z = 4;
							y = 4;
							break;
						}
					default:
					}
				}
				switch(x) {
				case 0:
					tempTxt += ", ";
					break;
				case 1:
					tempTxt += ", and ";
					break;
				case 2:
					tempTxt += " from this location.";
					break;
				default: 
				}
			}
			addText(tempTxt);
			break;
		case 2:
			tempTxt = "You may travel ";
			for(int x = 0; x < 2; x++) {
				for(int y = z; y < 4; y++) {
					switch(y) {
					case 0:
						if(currentRoom.getNorth() != 0) {
							tempTxt += "north";
							z = 1;
							y = 4;
							break;
						}
					case 1:
						if(currentRoom.getSouth() != 0) {
							tempTxt += "south";
							z = 2;
							y = 4;
							break;
						}
					case 2:
						if(currentRoom.getEast() != 0) {
							tempTxt += "east";
							z = 3;
							y = 4;
							break;
						}
					case 3:
						if(currentRoom.getWest() != 0) {
							tempTxt += "west";
							z = 4;
							y = 4;
							break;
						}
					default:
					}
				}
				switch(x) {
				case 0:
					tempTxt += " and ";
					break;
				case 1:
					tempTxt += " from this location.";
					break;
				default: 
				}
			}
			addText(tempTxt);
			break;
		case 1:
			if(currentRoom.getNorth() != 0) addText("You may only travel north from this location.");
			else if(currentRoom.getSouth() != 0) addText("You may only travel south from this location.");
			else if(currentRoom.getEast() != 0) addText("You may only travel east from this location.");
			else addText("You may only travel west from this location.");
			break;
		default:
		}

		/* -----> Current SOCKET Example
    	Socket socket = null;
    	DataOutputStream dataOutputStream = null;
    	DataInputStream dataInputStream = null;

    	try {
    		socket = new Socket(SERVER_IP, 8888); // Adjust the IP Address to match the SocketTestServer host!
    		dataOutputStream = new DataOutputStream(socket.getOutputStream());
    		dataInputStream = new DataInputStream(socket.getInputStream());
    		dataOutputStream.writeUTF("The Cavdam Client user LOOKS!");
    		addText(dataInputStream.readUTF());
    	}
    	catch (UnknownHostException e) { e.printStackTrace(); }
    	catch (IOException e) { e.printStackTrace(); }
    	catch (Exception e) { e.printStackTrace(); }
    	finally {
    		if (socket != null) {
    			try { socket.close(); }
    			catch (IOException e) { e.printStackTrace(); }
    		}

    		if (dataOutputStream != null) {
    			try { dataOutputStream.close(); }
    			catch (IOException e) { e.printStackTrace(); }
    		}

    		if (dataInputStream != null) {
    			try { dataInputStream.close(); }
    			catch (IOException e) { e.printStackTrace(); }
    		}
    	}
		 */
	}

	/*==================================================================*\
    || [TXTM]              On-Screen Text Management                    ||
    \*==================================================================*/

	private int TEXT_STORAGE_MAX_LINES = 24; // The number of "lines" retained for on-screen display.

	public void addText(String newText) {
		// Add a new string to the text to display on screen.
		textStorage.add(newText);

		// Truncate earlier lines of text when there is too much to display.
		while(textStorage.size() > TEXT_STORAGE_MAX_LINES) {
			textStorage.remove(0);
		}

		// Refresh the text displayed on screen.
		refreshText();
	}

	public void appendText(String newText) {
		// Appends a new string to the most recent line of text displayed on screen.
		if(!textStorage.lastElement().equalsIgnoreCase(null)) {
			String tempText = "";
			tempText = textStorage.lastElement();
			tempText += newText;

			// Replace the last line with the new, appended line of text.
			textStorage.removeElementAt(textStorage.size()-1);
			textStorage.add(tempText);

			// Refresh the text displayed on screen.
			refreshText();
		}
	}

	public void refreshText() {
		// Gather lines of text from the vector.
		String tempText = "";
		for(int x = 0;  x < textStorage.size(); x++) {
			tempText += "\n" + textStorage.elementAt(x);
		}

		// Text displayed on the screen is refreshed.
		tvDisplay.setText(tempText);

		// Scroll to bottom of ScrollView.
		scrollToBottom();
	}

	private void scrollToBottom() {
		svDisplay.post(new Runnable() { 
			public void run() { 
				svDisplay.smoothScrollTo(0, tvDisplay.getBottom());
			} 
		});
	}

}